package cn.wyz.org.service.impl;

import cn.wyz.basic.service.impl.BaseServiceImpl;
import cn.wyz.org.domain.Department;
import cn.wyz.org.mapper.DepartmentMapper;
import cn.wyz.org.service.IDepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class DepartmentServiceImpl extends BaseServiceImpl<Department> implements IDepartmentService {
    @Autowired
    private DepartmentMapper mapper;

    @Override
    @Transactional
    public void insert(Department department) {
        mapper.insert(department);
        this.update(department);
    }

    /**
     * 在修改的服务层,需要对新增的部门进行一个上级部门路径id进行回显
     * 因为这个上级部门id回显就是无限极树的回显
     * 1.在新增的xml中,增加返回自增主键id的属性<insert id="insert" useGeneratedKeys="true" keyColumn="id" keyProperty="id"
     * 2.拿到id以后在服务层通过新增时带回来的id,对自己的部门路径id进行一个拼接,手动设定
     * 3.在新增服务层调用this.update(department),在新增的时候就自行配置dirPath_id,直接传回后端就能拿到数据回显
     * @param department
     */
    @Override
    @Transactional
    public void update(Department department) {
        String dirPath3 = "";
            if(department.getParent() == null){
                //1.顶级部门  拼接/+自己id
                dirPath3 = "/"+department.getId();
            }else {
                //2.非顶级部门,拼接上级部门的dirth_id+/+自己的id
                //通过id查询,吧parent_id传进去查到上级部门,然后拼接
                Department parent1 = mapper.selectById(department.getParent().getId());
                dirPath3 = parent1.getDirPath()+"/"+department.getId();
            }
            department.setDirPath(dirPath3);
        mapper.update(department);
    }


    /**
     * 1.一次性查出所有数据,放在内存中
     * 2.找到顶级的单位,放入firstCurseType,只需要返回最上层,随便命名
     * 3.让 不是顶级的每条数据 都去找自己的上级部门
     * @return
     */
    @Override
    public List<Department> queryTree() {
        //1.一次性查出所有数据,放在内存中
        List<Department> departments = mapper.selectAll();
        /*为了后续方便查询,这里使用效率最高的方式,将集合中的数据在遍历中存到map里面,通过key=v的形式精准查找
        * dept数据集合里为id+对象,通过id存下各个对象的值
        * map和list用多态
        */
        Map<Long, Department> allDepts = new HashMap<>();
        for (Department department : departments) {
            allDepts.put(department.getId(),department);
        }
        //2.在前端中,要让上级部门逐级返回(不包括自己的id)需要传入一个对象{id = 7},所以要自己拼接一个,先做一个空的list出来
        List<Department> firstCurseType = new ArrayList<>();
        for (Department tempDept : departments) {
            //2.1进行一个保守的if判断,如果parent_id是空的就是顶级
            if(tempDept.getParent_id() == null){
                firstCurseType.add(tempDept);
            }//3.如果不是顶级,那么就在这个循环中去找到自己的上级部门,然后存入上级的children封装字段中
            else{
                /*
                    3.1 allDepts最先声明的是一个map,该map的key值是Long类型的,在t_department表中,每条数据的parent_id就是与自身的id关联的
                    所以这里直接用 allDepts.get(Long)来获取到对应的存入map的department对象,这些就是当前遍历的tempDept部门对象的上级部门
                 */
                Department parentDept = allDepts.get(tempDept.getParent_id());
                if(parentDept != null){
                    /*3.2 children字段是一个集合,不能直接set,要不然又要遍历,直接拿到集合用add的方式
                        就在这个循环中把由上级部门的子级存入对应的上级
                     */
                    parentDept.getChildren().add(tempDept);
                }
            }
        }//3.3 我们只需要从最上级开始拿,子级会自动在循环中通过查询map的key来存入对应上级部门的children集合中
        return firstCurseType;
    }


}
